package main;

import java.util.HashSet;

import org.jblas.DoubleMatrix;
import org.jblas.Geometry;

public class Subseq {
	DoubleMatrix seq;
	int begin;

	private Subseq() {
	};

	public Subseq(int begin, double[][] ar) {
		seq = new DoubleMatrix(ar);
		this.begin = begin;
	}

	public Subseq(int begin, DoubleMatrix m) {
		seq = m;
		this.begin = begin;
	}

	public Subseq(HashSet<Subseq> cluster) {
		if (cluster.size() > 0) {
			Subseq pattern = (Subseq) (cluster.toArray()[0]);
			Subseq avg = new Subseq();
			DoubleMatrix matrix = DoubleMatrix.zeros(pattern.getMatrix()
					.getRows(), pattern.getMatrix().getColumns());
			for (Subseq el : cluster) {
				matrix.addi(el.getMatrix());
			}
			matrix.divi(cluster.size());
			seq = matrix;
			begin = 0;
		}
	}

	public String toString() {
		if (seq != null)
			return seq.toString() + "\n";
		else
			return "empty";
	}

	public DoubleMatrix getMatrix() {
		return seq;
	}

	public double distance(Subseq sub2) {
		double distance = 0;
		if (seq.equals(sub2.getMatrix()))
			return 0;
		else {
			DoubleMatrix row;
			DoubleMatrix row1;
			for (int i = 0; i < seq.getRows(); i++) {
				row = seq.getRow(i);
				row1 = sub2.getMatrix().getRow(i);
				for (int k = 0; k < row.length; k++) {
					distance += Math.pow(row.get(k) - row1.get(k), 2);
				}
			}

		}

		return Math.sqrt(distance);
	}

	public double stsDistance(Subseq sub2) {
		double distance = 0;
		if (seq.equals(sub2.getMatrix()))
			return distance;
		else {
			DoubleMatrix temp = stsMatrix();
			Subseq t = new Subseq(0, temp);
			Subseq t2 = new Subseq(0,sub2.stsMatrix());
			return t.distance(t2);
			//return temp.distance1(sub2.stsMatrix());
		}
	}
	
	public DoubleMatrix stsMatrix(){
		double[][] ar = new double[seq.getRows()-1][seq.getColumns()];
		for (int i=0; i<seq.getColumns(); i++){
			DoubleMatrix column = seq.getColumn(i);
			for(int k=1; k<column.getRows(); k++){
				ar[k-1][i] = seq.get(k,i)-seq.get(k-1,i); 
			}
		}
		return new DoubleMatrix(ar);
	}

	public static double stdev(double[] ar) {
		double dev = 0;
		double avg = 0;
		double avgs = 0;
		for (int i = 0; i < ar.length; i++) {
			avg += ar[i];
			avgs += Math.pow(ar[i], 2);
		}
		avg /= ar.length;
		avgs /= ar.length;
		dev = Math.sqrt((ar.length / (ar.length - 1))
				* (avgs - Math.pow(avg, 2)));
		return dev;
	}

	public static double avg(double[] ar) {
		double avg = 0;
		for (int i = 0; i < ar.length; i++) {
			avg += ar[i];
		}
		avg /= ar.length;
		return avg;
	}

	public Subseq normalize() {
		for (int i = 0; i < seq.getColumns(); i++) {
			DoubleMatrix column = seq.getColumn(i);
			double[] col = column.data;
			double avg = avg(col);
			double stdev = stdev(col);
			double max = column.max();
			for (int k = 0; k < column.getLength(); k++) {
				seq.put(k, i, (seq.get(k, i) - avg) / stdev);
			//	seq.put(k, i, seq.get(k,i)/max);
			}
		}
		return this;
	}
	
	public Subseq normalize1(){
		
		
		Geometry.normalizeColumns(seq);
		return this;
	}
}
